package login_register

import (
	"context"
	"github.com/bwmarrin/snowflake"
	"github.com/google/uuid"
	"internal/store/redis"
	"internal/util"
	"math/rand"
	"strconv"
	"sync"
	"time"
)

const (
	UserId              int64  = 5000000               // 初始用户id
	RedisRegisterUserId string = "RedisRegisterUserId" // 存储用户id的redis的key
)

var ctx = context.Background()

// SerializeNumbers 序列化数字接口
type SerializeNumbers interface {
	GetUserid() int64
}

// UUID UUID算法生成用户id
type UUID struct{}

func (u UUID) GetUserid() int64 {
	uid, err := uuid.NewRandom()
	if err != nil {
		util.LogSrv.Error("UUID generate Error:  %v", err)
	}
	userID := uuid.Must(uid, nil).ID()
	return int64(userID)
}

// Snowflake Snowflake算法
type Snowflake struct {
}

func (s Snowflake) GetUserid() int64 {
	node, err := snowflake.NewNode(1)
	if err != nil {
		util.LogSrv.Error("Snowflake generate Error: %v", err)
	}
	return node.Generate().Int64()
}

// DateTimeRandom 时间戳和随机数
type DateTimeRandom struct{}

func (d DateTimeRandom) GetUserid() int64 {
	// 生成一个纳秒级别书剑种子
	seed := time.Now().UnixNano()
	rand.New(rand.NewSource(seed))
	return time.Now().UnixNano() + int64(rand.Intn(1000))
}

// RedisIncrement redis递增
type RedisIncrement struct{}

func (r RedisIncrement) GetUserid() int64 {
	ctx := context.Background()
	userid, err := redis.GetRedisConn().Incr(ctx, RedisRegisterUserId).Result()
	if err != nil {
		util.LogSrv.Error("Redis generate Error:  %v", err)
	}
	return userid
}

// Custom 定义生成Userid
type Custom struct {
	mutex sync.Mutex
}

func (c *Custom) GetUserid() int64 {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	ok, err := redis.GetRedisConn().Exists(ctx, RedisRegisterUserId).Result()
	if err != nil {
		util.LogSrv.Error("Redis check key error: %s", err.Error())
	}
	if ok == 0 {
		err := redis.GetRedisConn().Set(ctx, RedisRegisterUserId, UserId, 0).Err()
		if err != nil {
			util.LogSrv.Error("Redis set key error: %s", err.Error())
		}
	}
	err = redis.GetRedisConn().Incr(ctx, RedisRegisterUserId).Err()
	if err != nil {
		util.LogSrv.Error("Redis generate userid Incr Error: %s", err)
	}
	userid, err := redis.GetRedisConn().Get(ctx, RedisRegisterUserId).Result()
	if err != nil {
		util.LogSrv.Error("Redis get userid Error: %s", err)
	}
	useridInt64, err := strconv.ParseInt(userid, 10, 64)
	return useridInt64
}

// GenerateUserid 生成用户id
type GenerateUserid struct {
	Title            string
	GenerateStrategy SerializeNumbers
}

// SetAlgorithmNum 生成算法策略
func (g *GenerateUserid) SetAlgorithmNum(serializeNumbers SerializeNumbers) {
	g.GenerateStrategy = serializeNumbers
}

// GetAlgorithmNum 获取算法生成的数字
func (g *GenerateUserid) GetAlgorithmNum() int64 {
	if g.GenerateStrategy == nil {
		util.LogSrv.Error("GenerateStrategy is nil!")
	}
	return g.GenerateStrategy.GetUserid()
}

// GetAccountDA 对外获取用户id
func GetAccountDA() int64 {
	AlgorithmNum := &GenerateUserid{}
	// 设置策略-选用自定义算法生成AccountDA
	AlgorithmNum.SetAlgorithmNum(&Custom{})
	return AlgorithmNum.GetAlgorithmNum()
}
